package com.alawn.security.config.realm;

import java.time.LocalDate;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import com.alawn.framework.core.utils.ShiroUtils;
import com.alawn.framework.services.enums.UserStatus;
import com.alawn.framework.services.enums.UserType;
import com.alawn.framework.services.security.User;
import com.alawn.security.config.token.SecurityToken;
import com.alawn.security.exception.FreezeAccountException;
import com.alawn.security.exception.UnactivatedAccountException;
import com.alawn.security.service.SecurityService;

public class ShiroRealm extends AuthorizingRealm {

	@Autowired
	private SecurityService securityService;

	// 授权，每次操作都会进入，对权限的重新获取
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		User user = (User) principals.getPrimaryPrincipal();
		if (UserType.ADMIN.equals(user.getType())) {
			authorizationInfo.addRole("admin");
			authorizationInfo.addStringPermission("*:*");
			return authorizationInfo;
		}
		authorizationInfo.setRoles(securityService.findRoles(user.getUsername()));
		authorizationInfo.setStringPermissions(securityService.findPermissions(user.getUsername()));
		return authorizationInfo;
	}

	// 认证，只有登入时进入
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		SecurityToken frontToken = (SecurityToken) token;
		User user = securityService.findByUsername(frontToken.getUsername());

		if (user == null || user.isDeleted()) {
			throw new UnknownAccountException();
		} else if (UserStatus.LOCKED.equals(user.getStatus())) {
			throw new LockedAccountException();
		} else if (UserStatus.FREEZE.equals(user.getStatus()) && user.getFreezeDate().isBefore(LocalDate.now())) {
			throw new FreezeAccountException();
		} else if (UserStatus.UNACTIVATED.equals(user.getStatus())) {
			throw new UnactivatedAccountException();
		}
		ShiroUtils.getSession().setAttribute("shiroUser", user);
		return new SimpleAuthenticationInfo(user, user.getPassword(), ByteSource.Util.bytes(user.getCredentialsSalt()),
				getName());
	}

}